// liente.cpp: implementation of the Cliente class.
//
//////////////////////////////////////////////////////////////////////

#include "Cliente.h"
#include "logica.h"

int entro=0;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

Cliente::Cliente(int puerto, std::string ip)
{
	//creo y seteo el socket cliente
	socketClient.setPort(puerto);
	socketClient.setipAddress(ip);
	//inicializo los handlers que manejaran los mensajes cliente/servidor
	this->initHandlers();
	this->nivelActual = NULL;
	this->listaTex = new std::list<textura*>();
	this->jugador1 = NULL;
	this->jugador2 = NULL;
	this->Tejo = NULL;
	this->sincronized = false;
	this->loading = true;
	this->end = false;
	estadoBonus = NO_ACTIVO;
	estadoBonusAnterior = NO_ACTIVO;

}

Cliente::~Cliente()
{
	delete (this->jugador1);
	delete (this->jugador2);
	delete (this->Tejo);
	delete(this->receiver);
//	delete(textura_bonus);
	
	MapObservers::iterator it;
	
	//destruyo handlers
	for (it = this->fromServerHandlers.begin();it != this->fromServerHandlers.end();it++) {
		delete((it)->second);
	}

	//destruyo lista texturas
	std::list<textura*>::iterator itTex;
	for (itTex = this->listaTex->begin(); itTex != listaTex->end(); itTex++) {
		//destruto cada textura
		delete(*itTex);
	}
	delete(this->listaTex);


}

void Cliente::initHandlers() {

	this->fromServerHandlers[SINCRONIZACION] = new HandlerSincronizacion(this);
	this->fromServerHandlers[SINCRO_IMAGEN] = new HandlerImagenes(this);
	this->fromServerHandlers[GRAFICAR] = new HandlerGraficar(this);
	this->fromServerHandlers[EMPEZAR] = new HandlerStart(this);
	this->fromServerHandlers[TERMINAR] = new HandlerEnd(this);

}

void Cliente::conectar() {
	socketClient.conectar();
}

void Cliente::run() {
	sdlHelper::sdlInit(SDL_INIT_TIMER | SDL_INIT_VIDEO);
	pantalla::getPantalla();	
	
	//instancio los dos threads
	//thread que recibe y grafica
	this->receiver = new Receiver(this->socketClient,this->fromServerHandlers,this);

	//thread que envia y escucha eventos
	
	logger::getInstancia()->logCliente("Starteando los recvs y senders");
	//en teoria aca ya estamos conectados, asi que lo que tenemos que hacer es largar
	//los dos threads a correr, a saber:
	
	this->receiver->start();	
	
	try{
		while (this->socketClient.isConnected()) {
			Uint8 *tecla;     		
			int deteccionDeEvento = SDL_PollEvent(NULL);

			// SI HAY EVENTOS..

			if (deteccionDeEvento == 1) {
				tecla = SDL_GetKeyState(NULL);
				
				if (tecla[SDLK_SPACE]) {
					this->mandarEventoTeclado(DISPARO);
				}

				if (tecla[SDLK_DOWN ]) {
					this->mandarEventoTeclado(ABAJO);
				}

				if (tecla[SDLK_UP ]) {
					this->mandarEventoTeclado(ARRIBA);
				}

			} //FIN DETECCION EVENTOS	
			//graficar();

			this->sleep(50);

		}
	} catch(IOException* ex){
		logger::getInstancia()->logCliente("Se Desconecto el otro cliente");
		delete ex;
	}
	//this->receiver->join();
	//this->sender->join();

}

void Cliente::agregarTextura(textura* tex) {
	this->listaTex->push_back(tex);
}

void Cliente::setNuevoNivel(Nivel* nivel){
	logger::getInstancia()->logCliente("SET NUEVO NIVEL");
	this->nivelActual = nivel;
}

void Cliente::empezarNuevoNivel(){
	sdlHelper::blitSurface(pantalla::getPantalla(),NULL,pantalla::getBuffer(),NULL);
	logger::getInstancia()->logCliente("EMPEZANDO NUEVO NIVEL");
	if(jugador1 == NULL){
		jugador1 = new pad(punto(100,100),20,100,pantalla::getBuffer()); 
		jugador1->setColorRellenoFigura(new color(100,100,100));
		jugador2 = new pad(punto(500,100),20,100,pantalla::getBuffer()); 
		jugador2->setColorRellenoFigura(new color(100,100,100));
		Tejo = new tejo(punto(110,100),5,pantalla::getBuffer());
		Tejo->setColorRellenoFigura(new color(100,22,250));
		Tejo->setColorBordeFigura(new color(100,22,250));
	}
	listaFiguras::iterator it = nivelActual->getListaFiguras()->begin();
	
//	sdlHelper::blitSurface(pantalla::getPantalla(),NULL,pantalla::getBuffer(),NULL);

	logger::getInstancia()->logCliente("GRAFICANDO COSAS");
	for(;it!=nivelActual->getListaFiguras()->end();it++){
		(*it)->graficar();
	}

	
	SDL_Rect offset;
	offset.x = 0;
	offset.y = 30;
	offset.h = 470;
	offset.w = 1000;
	
	
	sdlHelper::blitSurface(pantalla::getPantalla(),&offset,pantalla::getBuffer(),&offset);


	sdlHelper::flip(pantalla::getPantalla());

	
	//SDL_Blitsurface(pantalla::getPantalla(),NULL,pantalla::getBuffer(),NULL);
	//SDL_Flip(pantalla::getPantalla());
	logger::getInstancia()->logCliente("NUEVO NIVEL");
	this->setSincronized(true);
	
	
}


void Cliente::graficar(){

	int static _puntos1;
	int static _puntos2;

	if (this->isSincronized()) {

		//Bonus
		
		listaFiguras::iterator it = nivelActual->getListaFiguras()->begin();
		char * bonus_a_figura;
		bonus_a_figura = new char[200];
		int i;
		if(estadoBonus != estadoBonusAnterior){
			switch(estadoBonus){
			case ACTIVO:
						for(i=0;it!=nivelActual->getListaFiguras()->end();it++,i++){
							if (i == this->posicion_bonus) {
								colorAnterior = (*it)->getColorRellenoGrafico();
								(*it)->setColorRellenoFigura(new color(0,150,250));
								(*it)->setColorBordeFigura(new color(150,150,150));
								(*it)->algoritmoGraficar(pantalla::getBuffer());								
							}
						}
						std::cout << "ACTIVO BONUS\n";
						break;
			case NO_ACTIVO:
						for(i=0;it!=nivelActual->getListaFiguras()->end();it++,i++){
							if (i == this->posicion_bonus) {
								if((*it)->getColorRellenoGrafico() != NULL){
									delete((*it)->getColorRellenoGrafico());
								}
								(*it)->setColorRellenoFigura(colorAnterior);
								(*it)->algoritmoGraficar(pantalla::getBuffer());
								colorAnterior=NULL;
							}
						}
						std::cout << "DESACTIVO BONUS\n";
						break;
			case EN_USO:
						for(i=0;it!=nivelActual->getListaFiguras()->end();it++,i++){
							if (i == this->posicion_bonus) {
								if((*it)->getColorRellenoGrafico() != NULL){
									delete((*it)->getColorRellenoGrafico());
								}
								(*it)->setColorRellenoFigura(colorAnterior);
								(*it)->algoritmoGraficar(pantalla::getBuffer());
								colorAnterior=NULL;
							}
						}
						break;
				default:
					break;
			}
			estadoBonusAnterior = estadoBonus;
		}
		delete[] bonus_a_figura;

		// Bonus
	

		
		//pantalla::lockSurface();


		//Tejo->setRadio(15);
		punto puntoLimpiador;

		puntoLimpiador.setX(0);
		
		puntoLimpiador.setY(0);
		
		

		pad limpiador(puntoLimpiador,1000,30,pantalla::getBuffer());  //*
		color* negro=new color (0,0,0);
		limpiador.setColorRellenoFigura(negro);

		if(entro<10){
			limpiador.graficar();
			entro++;
		}
	

		mostrarPantallaJugando(pantalla::getPantalla(),this->puntaje1 , this->puntaje2, 0);
		


		SDL_Rect offset;
		punto centro_tejo;

		centro_tejo = Tejo->getCentro();
	//	offset.x = centro_tejo.getX()-(Tejo->getRadio()/2);
	//	offset.y = centro_tejo.getY()-(Tejo->getRadio()/2);;
	//	offset.h = 2*(Tejo->getRadio()/2);
	//	offset.w = 2*(Tejo->getRadio()/2);

		offset.x = 0;
		offset.y = 30;
		offset.h = 470;
		offset.w = 1000;


		
		//sdlHelper::blitSurface(pantalla::getBuffer(),NULL,pantalla::getPantalla(),NULL);
		sdlHelper::blitSurface(pantalla::getBuffer(),&offset,pantalla::getPantalla(),&offset);

		
		jugador1->graficar();
		jugador2->graficar();
		Tejo->desplazar();

		//pantalla::unlockSurface();
		
	
	
		if (_puntos1!=this->puntaje1||_puntos2!=this->puntaje2){	
			limpiador.graficar();
			mostrarPantallaJugando(pantalla::getPantalla(),this->puntaje1 , this->puntaje2, 0);
		}
		
	
		sdlHelper::flip(pantalla::getPantalla());

		_puntos1 = this->puntaje1;
		_puntos2 = this->puntaje2;

	} else if (!this->isEnd() && this->isLoading()){
		mostrarPantallaLoading(pantalla::getPantalla());
	}
	
}

void Cliente::mandarEventoTeclado(EnumMovimiento movimiento) {
	codigoClienteServer code = ACTUALIZACION_PAD;
	int size = sizeof(movimiento);
	this->socketClient.getOutputStream().write(reinterpret_cast<char*>(&code),sizeof(code));
	this->socketClient.getOutputStream().write(reinterpret_cast<char*>(&size),sizeof(size));
	this->socketClient.getOutputStream().write(reinterpret_cast<char*>(&movimiento),size);
}


void Cliente::mostrarUltimaPantalla(int puntaje1, int puntaje2) {
	mostrarPantallaFin(pantalla::getPantalla(),puntaje1>puntaje2);
	this->sleep(50000);
}